/*
Copyright [2020] [https://www.xiaonuo.vip]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Snowy采用APACHE LICENSE 2.0开源协议，您在使用过程中，需要注意以下几点：

1.请不要删除和修改根目录下的LICENSE文件。
2.请不要删除和修改Snowy源码头部的版权声明。
3.请保留源码和相关描述文件的项目出处，作者声明等。
4.分发源码时候，请注明软件出处 https://gitee.com/xiaonuobase/snowy
5.在修改包名，模块名称，项目代码等时，请注明软件出处 https://gitee.com/xiaonuobase/snowy
6.若您的项目无法满足以上几点，可申请商业授权，获取Snowy商业授权许可，请在官网购买授权，地址为 https://www.xiaonuo.vip
 */
package vip.xiaonuo.app.modular.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import vip.xiaonuo.app.core.consts.AppConstant;
import vip.xiaonuo.app.modular.pay.result.PayInfoResult;
import vip.xiaonuo.app.modular.recharge.entity.AppRechargeOrder;
import vip.xiaonuo.app.modular.recharge.service.AppRechargeOrderService;
import vip.xiaonuo.app.modular.vip.entity.AppVipOrder;
import vip.xiaonuo.app.modular.vip.service.AppVipOrderService;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.core.exception.enums.ParamException;
import vip.xiaonuo.core.exception.enums.ParamExceptionEnum;
import vip.xiaonuo.core.factory.PageFactory;
import vip.xiaonuo.core.pojo.page.PageResult;
import vip.xiaonuo.core.util.PoiUtil;
import vip.xiaonuo.app.modular.pay.entity.AppAlipayConfig;
import vip.xiaonuo.app.modular.pay.enums.AppAlipayConfigExceptionEnum;
import vip.xiaonuo.app.modular.pay.mapper.AppAlipayConfigMapper;
import vip.xiaonuo.app.modular.pay.param.mgr.AppAlipayConfigParam;
import vip.xiaonuo.app.modular.pay.service.AppAlipayConfigService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;

/**
 * 支付宝支付表service接口实现类
 *
 * @author 郑雄伟
 * @date 2023-10-08 11:14:30
 */
@Service
public class AppAlipayConfigServiceImpl extends ServiceImpl<AppAlipayConfigMapper, AppAlipayConfig> implements AppAlipayConfigService {


    @Resource
    private AppRechargeOrderService appRechargeOrderService;
    @Resource
    private AppVipOrderService appVipOrderService;


    @Override
    public AppAlipayConfig getWeightPayInfo() {
        //取第一条
        AppAlipayConfig appAliPayConfig = this.list().get(0);

        return appAliPayConfig;
    }

    @Override
    public PayInfoResult tradeWapPay(Long userId, String mobileSpec, Integer projectType, Integer packageId, BigDecimal money) {
        //从数据库支付请求必要参数
        AppAlipayConfig info = getWeightPayInfo();
        //判断payType
        switch (projectType) {
            case 1: // 支付类型1 (钻石充值)
                //添加订单
                AppRechargeOrder appRechargeOrder
                        = appRechargeOrderService.tradeWapPay(
                        userId,
                        mobileSpec,
                        packageId,
                        money,
                        AppConstant.ALI_PAY_ONE);
                //支付宝预处理
                AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式
                model.setBody("充值");//对一笔交易的具体描述信息。如果是多种商品，请将商品描述字符串累加传给body。
                model.setSubject("钻石充值");//商品名称
                model.setOutTradeNo(appRechargeOrder.getOrderNo()); //商户订单号(自动生成)
                model.setTotalAmount(appRechargeOrder.getMoney().setScale(2, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());//支付金额
                model.setProductCode("QUICK_WAP_PAY");//销售产品码（固定值）
                //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeWapPayRequest webRequest = new AlipayTradeWapPayRequest();
                webRequest.setBizModel(model);
                webRequest.setNotifyUrl(info.getNotifyUrl() + "/" + info.getAppId() + "/1");//异步回调地址（后台）  拼接appId
                webRequest.setReturnUrl(info.getReturnUrl());
                //返回支付宝订单信息(预处理)
                AlipayClient alipayClient = new DefaultAlipayClient(
                        info.getGateWayUrl(),
                        info.getAppId(),
                        info.getAppPrivateKey(),
                        info.getFormat(),
                        info.getCharset(),
                        info.getAppPublicKey(),
                        info.getSignType()
                );
                PayInfoResult payInfoResult = new PayInfoResult();
                try {
                    String orderString = alipayClient.pageExecute(webRequest, "get").getBody();
                    payInfoResult.setOrderNo(appRechargeOrder.getOrderNo());
                    payInfoResult.setPayUrl(orderString);
                } catch (Exception e) {
                    return payInfoResult;
                }
                return payInfoResult;
            case 2: //支付类型2  （会员充值）

                //添加订单
                AppVipOrder appVipOrder = appVipOrderService.tradeWapPay(
                        userId,
                        mobileSpec,
                        packageId,
                        money,
                        AppConstant.ALI_PAY_ONE);
                //支付宝预处理
                AlipayTradeWapPayModel model1 = new AlipayTradeWapPayModel(); //SDK已经封装掉了公共参数，这里只需要传入业务参数。以下方法为sdk的model入参方式
                model1.setBody("充值");//对一笔交易的具体描述信息。如果是多种商品，请将商品描述字符串累加传给body。
                model1.setSubject("钻石充值");//商品名称
                model1.setOutTradeNo(appVipOrder.getOrderNo()); //商户订单号(自动生成)
                model1.setTotalAmount(appVipOrder.getMoney().setScale(2, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());//支付金额
                model1.setProductCode("QUICK_WAP_PAY");//销售产品码（固定值）
                //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称：alipay.trade.app.pay
                AlipayTradeWapPayRequest webRequest1 = new AlipayTradeWapPayRequest();
                webRequest1.setBizModel(model1);
                webRequest1.setNotifyUrl(info.getNotifyUrl() + "/" + info.getAppId() + "/1");//异步回调地址（后台）  拼接appId
                webRequest1.setReturnUrl(info.getReturnUrl());
                //返回支付宝订单信息(预处理)
                AlipayClient alipayClient1 = new DefaultAlipayClient(
                        info.getGateWayUrl(),
                        info.getAppId(),
                        info.getAppPrivateKey(),
                        info.getFormat(),
                        info.getCharset(),
                        info.getAppPublicKey(),
                        info.getSignType()
                );
                PayInfoResult payInfoResult1 = new PayInfoResult();
                try {
                    String orderString = alipayClient1.pageExecute(webRequest1, "get").getBody();
                    payInfoResult1.setOrderNo(appVipOrder.getOrderNo());
                    payInfoResult1.setPayUrl(orderString);
                } catch (Exception e) {
                    return payInfoResult1;
                }
                return payInfoResult1;

            default:
                throw new ParamException(ParamExceptionEnum.PARAM_ERROR);
        }

    }

    @Override
    public AppAlipayConfig getByAppId(String appId) {
        LambdaQueryWrapper<AppAlipayConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AppAlipayConfig::getAppId, appId);
        return this.getOne(queryWrapper);
    }

    @Override
    public PageResult<AppAlipayConfig> page(AppAlipayConfigParam appAlipayConfigParam) {
        QueryWrapper<AppAlipayConfig> queryWrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotNull(appAlipayConfigParam)) {

            // 根据权重1-100 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getWeight())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getWeight, appAlipayConfigParam.getWeight());
            }
            // 根据商户名称 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getMchName())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getMchName, appAlipayConfigParam.getMchName());
            }
            // 根据AppId 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getAppId())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getAppId, appAlipayConfigParam.getAppId());
            }
            // 根据开发者私钥 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getAppPrivateKey())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getAppPrivateKey, appAlipayConfigParam.getAppPrivateKey());
            }
            // 根据开发者公钥 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getAppPublicKey())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getAppPublicKey, appAlipayConfigParam.getAppPublicKey());
            }
            // 根据异步回调地址（多种订单模式根据 xxx_截取判断） 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getNotifyUrl())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getNotifyUrl, appAlipayConfigParam.getNotifyUrl());
            }
            // 根据支付成功返回地址 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getReturnUrl())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getReturnUrl, appAlipayConfigParam.getReturnUrl());
            }
            // 根据返回格式默认JSON 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getFormat())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getFormat, appAlipayConfigParam.getFormat());
            }
            // 根据字符集默认UTF-8 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getCharset())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getCharset, appAlipayConfigParam.getCharset());
            }
            // 根据网关默认：https://openapi.alipay.com/gateway.do 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getGateWayUrl())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getGateWayUrl, appAlipayConfigParam.getGateWayUrl());
            }
            // 根据签名类型默认RSA2 查询
            if (ObjectUtil.isNotEmpty(appAlipayConfigParam.getSignType())) {
                queryWrapper.lambda().eq(AppAlipayConfig::getSignType, appAlipayConfigParam.getSignType());
            }
        }
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    @Override
    public List<AppAlipayConfig> list(AppAlipayConfigParam appAlipayConfigParam) {
        return this.list();
    }

    @Override
    public void add(AppAlipayConfigParam appAlipayConfigParam) {
        AppAlipayConfig appAlipayConfig = new AppAlipayConfig();
        BeanUtil.copyProperties(appAlipayConfigParam, appAlipayConfig);
        this.save(appAlipayConfig);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<AppAlipayConfigParam> appAlipayConfigParamList) {
        appAlipayConfigParamList.forEach(appAlipayConfigParam -> {
            this.removeById(appAlipayConfigParam.getId());
        });
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(AppAlipayConfigParam appAlipayConfigParam) {
        AppAlipayConfig appAlipayConfig = this.queryAppAlipayConfig(appAlipayConfigParam);
        BeanUtil.copyProperties(appAlipayConfigParam, appAlipayConfig);
        this.updateById(appAlipayConfig);
    }

    @Override
    public AppAlipayConfig detail(AppAlipayConfigParam appAlipayConfigParam) {
        return this.queryAppAlipayConfig(appAlipayConfigParam);
    }

    /**
     * 获取支付宝支付表
     *
     * @author 郑雄伟
     * @date 2023-10-08 11:14:30
     */
    private AppAlipayConfig queryAppAlipayConfig(AppAlipayConfigParam appAlipayConfigParam) {
        AppAlipayConfig appAlipayConfig = this.getById(appAlipayConfigParam.getId());
        if (ObjectUtil.isNull(appAlipayConfig)) {
            throw new ServiceException(AppAlipayConfigExceptionEnum.NOT_EXIST);
        }
        return appAlipayConfig;
    }

    @Override
    public void export(AppAlipayConfigParam appAlipayConfigParam) {
        List<AppAlipayConfig> list = this.list(appAlipayConfigParam);
        PoiUtil.exportExcelWithStream("SnowyAppAlipayConfig.xls", AppAlipayConfig.class, list);
    }

}
